package me.helllp.dake.generator.engine;

import freemarker.template.TemplateException;
import lombok.Getter;
import lombok.Setter;
import me.helllp.dake.common.anno.MataGenerator;
import me.helllp.dake.generator.config.GeneratorEngineConfiguration;
import me.helllp.dake.generator.config.ProjectConfiguration;
import me.helllp.dake.generator.engine.service.ConfigurationGenerator;
import me.helllp.dake.generator.config.enums.MergeTypeEnum;
import me.helllp.dake.generator.meta.IThirdComponent;
import me.helllp.dake.generator.meta.PomMetaData;
import me.helllp.dake.generator.meta.ProjectMetaData;
import me.helllp.dake.generator.utils.FileAndPathUtils;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 生成项目的引擎
 */
@Getter
@Setter
@Service
public abstract class ProjectGenerator extends AbstractGenerator{
    /**
     * 项目原始的配置信息
     */
    private ProjectConfiguration projectConfiguration;

    /**
     * 项目的元数据信息，基于原始配置信息生成
     */
    @MataGenerator
    private ProjectMetaData projectMetaData;

    private PomGenerator pomGenerator;

    private ConfigurationGenerator configurationGenerator;

    public ProjectGenerator(ProjectConfiguration projectConfiguration) {
        this.projectConfiguration = projectConfiguration;
    }

    @Override
    public void initGenerator(GeneratorEngineConfiguration engineConfiguration) throws TemplateException, IOException, InvocationTargetException, IllegalAccessException {
        super.initGenerator(engineConfiguration);
        // 配置信息转换为元数据
        projectMetaData = MetaDataBuilder.builder(projectConfiguration);
        // 构造POM生成器
        pomGenerator = new PomGenerator(projectMetaData);
        pomGenerator.initGenerator(engineConfiguration);
        // 基础框架的依赖
        pomGenerator.addDependency(new PomMetaData("me.helllp", "dake-common", getEngineConfiguration().getDakeVersion()));
        pomGenerator.addDependency(new PomMetaData("me.helllp", "dake-core", getEngineConfiguration().getDakeVersion()));

        // 构造配置文件生成器
        configurationGenerator = new ConfigurationGenerator(projectMetaData);
        configurationGenerator.initGenerator(engineConfiguration);

        // 根据三方键配置修改pom和配置类
        List<PomMetaData> listPoms = Optional.ofNullable(this.getProjectMetaData().getThirdComponents()).orElse(Collections.emptyList())
            .stream().map(IThirdComponent::toDependency).flatMap(Collection::stream).collect(Collectors.toList());
        pomGenerator.addDependency(listPoms);

        Map<String,Object> settings = new HashMap<>();
        Optional.ofNullable(this.getProjectMetaData().getThirdComponents()).orElse(Collections.emptyList())
            .stream().forEach(data -> settings.putAll(data.toSpringBootSettings()));
        configurationGenerator.getProperties().putAll(settings);
    }

    @Override
    public void generator() throws IOException, TemplateException {
        if (getEngineConfiguration().getMergeType() == MergeTypeEnum.CREATE) {  // 清理相关目录文件
            FileUtils.deleteDirectory(FileAndPathUtils.pathAppend(projectMetaData.getProjectPath(), "src"));
        }

        // 创建项目相关目录
        FileAndPathUtils.makeDir(projectMetaData.getProjectPath());
        FileAndPathUtils.makeDir(projectMetaData.getSrcJavaPath());
        FileAndPathUtils.makeDir(projectMetaData.getSrcResourcePath());
        FileAndPathUtils.makeDir(projectMetaData.getTestJavaPath());
        FileAndPathUtils.makeDir(projectMetaData.getTestResourcePath());
        FileAndPathUtils.makePackage(projectMetaData.getSrcJavaPath(), projectMetaData.getBasePackage());
        FileAndPathUtils.makePackage(projectMetaData.getTestJavaPath(), projectMetaData.getBasePackage());
    }
}
